package rullekake.beans.util;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import rullekake.beans.CourseController;
import rullekake.entities.Course;
import rullekake.entities.Outcome;

/**
 * Genererer XML-fil med informasjon om et fag.
 * 
 */


@ManagedBean(name="xmlGenerator")
public class Xmlgenerator {

    @ManagedProperty(value="#{courseController}")
    CourseController courseController;

    public CourseController getCourseController() {
        return courseController;
    }

    public void setCourseController(CourseController courseController) {
        this.courseController = courseController;
    }

    public Xmlgenerator () {}

    /**
     * Genererer html-request og sender xml-fil til bruker
     *
     * @param courseCode emnekode
     */
    public void getCourseAsXml(String courseCode) {

        HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
        response.setContentType("application/force-download");
        String downloadFile = courseCode;
        response.addHeader("Content-Disposition", "attachment; filename=\"" + downloadFile + ".xml\"");
        try{

          DOMSource source = new DOMSource(createDocument(getCourseFromCourseCode(courseCode)));
          TransformerFactory transformerFactory = TransformerFactory.newInstance();
	  Transformer transformer = transformerFactory.newTransformer();
          ServletOutputStream out = response.getOutputStream();
          transformer.transform(source, new StreamResult(out));
          out.close();
        }catch (Exception exc){
          exc.printStackTrace();
        }
    }

    /**
     * Genererer xml-fil
     * @param course emne-objekt
     * @return zml-fil
     */
    private Document createDocument(Course course) {
        try{

	  DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
	  DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

	  //root elements
	  Document doc = docBuilder.newDocument();
	  Element rootElement = doc.createElement("course");
	  rootElement.setAttribute("institute", course.getFaculty().getInstitution().getInstitutionName());
          rootElement.setAttribute("faculty", course.getFaculty().getFacultyName());
          doc.appendChild(rootElement);

          addElementAndText(doc, rootElement, "courseCode", course.getCourseCode());
          addElementAndText(doc, rootElement, "courseName", course.getCourseName());
          addElementAndText(doc, rootElement, "courseNameNo", course.getCourseNameNo());
          addElementAndText(doc, rootElement, "courseworkRequirements", course.getCourseworkRequirements());
          addElementAndText(doc, rootElement, "courseworkRequirementsNo", course.getCourseworkRequirementsNo());
          addElementAndText(doc, rootElement, "courseContent", course.getCourseContent());
          addElementAndText(doc, rootElement, "courseContentNo", course.getCourseContentNo());
          addElementAndText(doc, rootElement, "formOfAssessment", course.getFormOfAssessment());
          addElementAndText(doc, rootElement, "formOfAssessmentNo", course.getFormOfAssessmentNo());
          addElementAndText(doc, rootElement, "previousKnowledge", course.getPreviousKnowledge());
          addElementAndText(doc, rootElement, "previousKnowledgeNo", course.getPreviousKnowledgeNo());
          addElementAndText(doc, rootElement, "readingList", course.getReadingList());
          addElementAndText(doc, rootElement, "resitRequirements", course.getResitRequirements());
          addElementAndText(doc, rootElement, "resitRequirementsNo", course.getResitRequirementsNo());
          addElementAndText(doc, rootElement, "studyActivites", course.getStudyActivities());
          addElementAndText(doc, rootElement, "studyActivitesNo", course.getStudyActivitiesNo());
          addElementAndText(doc, rootElement, "supportMaterial", course.getSupportMaterial());
          addElementAndText(doc, rootElement, "supportMaterialNo", course.getSupportMaterialNo());
          addElementAndText(doc, rootElement, "courseLanguage", ""+course.getCourseLanguage());
          addElementAndText(doc, rootElement, "ectsCredits", ""+course.getEctsCredits());
          addElementAndText(doc, rootElement, "semester", ""+course.getSemester());
          
          Element outcomes = doc.createElement("outcomes");
          for (Outcome o: course.getOutcomeCollection()) {
            Element outcome = doc.createElement("outcome");
              addElementAndText(doc, outcome, "type", Outcome.getTypeFromInt(o.getOutcomeType()));
              addElementAndText(doc, outcome, "text", o.getText());
              addElementAndText(doc, outcome, "textNo", o.getTextNo());
            outcomes.appendChild(outcome);
          }
          rootElement.appendChild(outcomes);

          return doc;

     }catch(ParserConfigurationException pce){
	  pce.printStackTrace();
     }
        return null;
    }

    /**
     * Henter emneobjekt ut fra emnekode
     * @param courseCode emnekode
     * @return emneobjekt
     */

    private Course getCourseFromCourseCode(String courseCode) {
        for (Course c: (DataModel<Course>)courseController.getItems()) {
            if (c.getCourseCode().equals(courseCode)) return c;
        }
        return null;
    }

    /**
     * Legger enkelt til tag/verdi-par i xml-filen
     *
     * @param doc
     * @param rootElement
     * @param title
     * @param value
     */

    private void addElementAndText(Document doc, Element rootElement, String title, String value) {
          Element e = doc.createElement(title);
	  e.appendChild(doc.createTextNode(((value==null)|| (value.equals("null")))?"":value));
	  rootElement.appendChild(e);

    }
}
